package com.android.lovely.ui.activity

import android.os.Bundle
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.TextPaint
import android.text.style.ClickableSpan
import android.view.View
import androidx.core.text.bold
import androidx.core.text.buildSpannedString
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ConcatAdapter
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.android.lovely.R
import com.android.lovely.const.CardUL
import com.android.lovely.const.CollectRobot
import com.android.lovely.data.CardDetailBean
import com.android.lovely.data.CardItem
import com.android.lovely.databinding.ActivityDetailBinding
import com.android.lovely.databinding.AdapterLoadingFooterBinding
import com.android.lovely.databinding.ItemDetailTitleBinding
import com.android.lovely.databinding.ViewDetailNoContentBinding
import com.android.lovely.ext.fullScreen
import com.android.lovely.ext.loadBlurredImage
import com.android.lovely.framework.BaseAdapter
import com.android.lovely.framework.BaseMvvmActivity
import com.android.lovely.framework.UIController.showToast
import com.android.lovely.room.BotCacheService
import com.android.lovely.room.BotCacheService.observeBot
import com.android.lovely.room.CacheProfile
import com.android.lovely.ui.adapter.DetailLoadAdapter
import com.android.lovely.ui.adapter.DetailRobotCardsAdapter
import com.android.lovely.ui.adapter.HomeTagsAdapter
import com.android.lovely.ui.chat.ChatMessageActivity
import com.android.lovely.ui.dialog.showLovelyDialog
import com.android.lovely.ui.viewmodel.DetailViewModel
import com.kotlin.extensions.appContext
import com.kotlin.extensions.bus.FlowBus
import com.kotlin.extensions.bus.flowOf
import com.kotlin.extensions.context.ContextExt.startPage
import com.kotlin.extensions.context.ContextExt.startPageClearTop
import com.kotlin.extensions.coroutine.CoroutineExt.launchSafety
import com.kotlin.extensions.view.ViewExt.addStatusBarMarginTop
import com.kotlin.extensions.view.ViewExt.clickable
import kotlinx.coroutines.flow.collectLatest
import kotlin.math.roundToInt

// 策略接口
interface ActionStrategy {
    fun execute()
}

// 收藏策略
class CollectRobotStrategy(
    private val viewModel: DetailViewModel,
) : ActionStrategy {
    override fun execute() {
        viewModel.collectTheRobot()
    }
}

// 解锁所有卡片策略
class UnlockAllCardsStrategy(
    private val viewModel: DetailViewModel,
    private val activity: DetailActivity
) : ActionStrategy {
    override fun execute() {
        val cardInfo = viewModel.currentCardDetail ?: return
        if (cardInfo.unlockCardNum >= cardInfo.allCardNum) {
            showToast(activity.getString(R.string.unlocked_all))
            return
        }
        activity.showUnlockAllDialog(cardInfo)
    }
}

/**
 * @author why
 * @date 2025/3/12 14:31
 */
class DetailActivity : BaseMvvmActivity<ActivityDetailBinding, DetailViewModel>() {

    private val headerAdapter by lazy { DetailHeaderAdapter() }
    private val emptyAdapter by lazy { DetailEmptyViewAdapter() }
    private val loadAdapter by lazy {
        DetailLoadAdapter(
            AdapterLoadingFooterBinding.inflate(
                layoutInflater, mBinding.rv, false
            )
        )
    }
    private val cardAdapter by lazy { DetailRobotCardsAdapter() }
    private val combinedAdapter =
        ConcatAdapter(ConcatAdapter.Config.Builder().setIsolateViewTypes(false).build())

    override fun initView(savedInstanceState: Bundle?) {
        setupScreenLayout()
        setupClickListeners()
        setupAdapters()
        initializeRobotData()
        setupCardList()

        if (!BotCacheService.doesBotExist(viewModel.robotId)) {
            showLoading()
        }
        loadAdapter.onLoadMoreListener = {
            viewModel.loadCardInfo()
        }


        lifecycleScope.observeBot(viewModel.robotId) {
            dismissLoading()
            it?.let { profile ->
                updateUIWithProfile(profile)
            }
        }
    }

    override suspend fun initData() {
        observeCardDetailFlow()
        observeCollectRobotFlow()
        observeCardUnlockFlow()
    }

    private fun setupScreenLayout() {
        fullScreen()
        mBinding.llTop.addStatusBarMarginTop()
    }

    private fun setupClickListeners() {
        mBinding.ivLeft.clickable {
            finish()
        }
        mBinding.collect.clickable {
            viewModel.collectTheRobot()
        }
        mBinding.report.clickable {
            startPage<OptimizationActivity>("user_id" to viewModel.robotId)
        }
        mBinding.chat.clickable {
            startPageClearTop<ChatMessageActivity>("id" to viewModel.robotId)
        }
        mBinding.unlockAll.clickable {
            UnlockAllCardsStrategy(viewModel, this).execute()
        }
    }

    private fun setupAdapters() {
        combinedAdapter.addAdapter(headerAdapter)
        combinedAdapter.addAdapter(cardAdapter)
    }

    private fun initializeRobotData() {
        viewModel.robotId = intent.getIntExtra("robot_id", 0)
        viewModel.obtainCardDetail()
    }

    private suspend fun observeCardDetailFlow() {
        lifecycleScope.launchSafety {
            viewModel.cardDetailFlow.collectLatest {
                mBinding.tvDiscount.isVisible = it.discount > 0
                mBinding.tvDiscount.text =  String.format(getString(R.string.pay_off2), "${((1 - it.discount) * 100).roundToInt()}%")

            }
        }
    }

    private suspend fun observeCollectRobotFlow() {
        lifecycleScope.launchSafety {
            FlowBus.flowOf<CollectRobot>().collectLatest {
                if (it.id == viewModel.robotId) {
                    toggleCollectState()
                }
            }
        }
    }

    private suspend fun observeCardUnlockFlow() {
        lifecycleScope.launchSafety {
            FlowBus.flowOf<CardUL>().collectLatest {
                updateUnlockedCards(it)
            }
        }
    }


    private fun updateUIWithProfile(profile: CacheProfile) {
        loadAdapter.isLoading = false
        mBinding.bg.loadBlurredImage(profile.background)
        mBinding.tvTitle.text = profile.name
        mBinding.collect.isSelected = profile.isCollect == 1
        mBinding.heart.text = profile.intimacyValue.toString()
        mBinding.tvTitle.helper.drawableRight = androidx.core.content.res.ResourcesCompat.getDrawable(
            resources,
            when (profile.gender) {
                1 -> R.drawable.icon_male_select
                2 -> R.drawable.icon_female_select
                else -> R.drawable.icon_unknow_select
            },
            null
        )
        headerAdapter.updateList(arrayListOf(profile))
        configureAdapterBasedOnProfile(profile)
    }

    private fun configureAdapterBasedOnProfile(profile: CacheProfile) {
        if ((profile.cardNum == 0&& profile.cards.isEmpty()) || !viewModel.hasMore) {
            showEmptyAdapter()
        } else {
            showCardAdapter(profile)
        }
    }

    private fun showEmptyAdapter() {
        combinedAdapter.removeAdapter(cardAdapter)
        combinedAdapter.removeAdapter(loadAdapter)
        combinedAdapter.addAdapter(emptyAdapter)
        emptyAdapter.updateList(arrayListOf(""))
    }

    private fun showCardAdapter(profile: CacheProfile) {
        combinedAdapter.removeAdapter(emptyAdapter)
        cardAdapter.submitList(profile.cards)
        if (!combinedAdapter.adapters.contains(loadAdapter)) {
            combinedAdapter.addAdapter(loadAdapter)
        }
        loadAdapter.loadMoreEnd = profile.cards.size >= profile.cardNum
        viewModel.currentPage = if (profile.cards.isEmpty()) 1 else 1 + (profile.cards.size / 10)
    }


    private fun setupCardList() {
        mBinding.rv.adapter = combinedAdapter
        mBinding.rv.layoutManager = GridLayoutManager(this, 2).apply {
            spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
                override fun getSpanSize(position: Int): Int {
                    val viewType = mBinding.rv.adapter?.getItemViewType(position)
                    return if (viewType == 100 || viewType == 888 || viewType == 101) spanCount else 1
                }
            }
        }
        cardAdapter.onItemClickListener = { item, position ->
            processCardItemClick(item, position)
        }
    }

    private fun toggleCollectState() {
        mBinding.collect.isSelected = mBinding.collect.isSelected.not()
        BotCacheService.updateBot(viewModel.robotId) {
            isCollect = if (mBinding.collect.isSelected) 1 else 0
        }
    }

    private fun updateUnlockedCards(cardUpdate: CardUL) {
        cardUpdate.ids.forEach { id ->
            cardAdapter.currentList.forEach { card ->
                if (card.id == id) {
                    card.isUnlock = true
                }
            }
        }
        cardAdapter.notifyDataSetChanged()
    }

    private fun processCardItemClick(card: CardItem, position: Int) {
        if (card.isUnlock) {
            BigCardActivity.start(
                this,
                viewModel.robotId,
                position,
                mBinding.tvTitle.text.toString(),
                cardAdapter.currentList
            )
        } else {
            lifecycleScope.launchSafety {
                viewModel.unlockSingleCard(card.id)
            }
        }
    }

    fun showUnlockAllDialog(cardInfo: CardDetailBean) {
        showLovelyDialog {
            setDialogTitle(getString(R.string.unlock_all_cards))
            setDialogMessage(createUnlockMessage(cardInfo.unlockAllPrice), true)
            setPositiveButton {
                viewModel.unlockAllCards()
            }
        }
    }

    private fun createUnlockMessage(count: Int): CharSequence {
        val agreement = String.format(getString(R.string.unlock_tip), count.toString())
        try {
            val spaBuilder = SpannableStringBuilder(agreement)
            val privacySpan = getString(R.string.gems)
            val serviceSpan = count.toString()
            spaBuilder.setSpan(
                object : ClickableSpan() {
                    override fun onClick(widget: View) {
                        // 处理点击事件
                    }
                    override fun updateDrawState(ds: TextPaint) {
                        super.updateDrawState(ds)
                        ds.color = resources.getColor(R.color.color_main)
                        ds.isUnderlineText = false
                        ds.clearShadowLayer()
                    }
                },
                spaBuilder.indexOf(privacySpan),
                spaBuilder.indexOf(privacySpan) + privacySpan.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )
            spaBuilder.setSpan(
                object : ClickableSpan() {
                    override fun onClick(widget: View) {
                        // 处理点击事件
                    }
                    override fun updateDrawState(ds: TextPaint) {
                        super.updateDrawState(ds)
                        ds.color = resources.getColor(R.color.color_main)
                        ds.isUnderlineText = false
                        ds.clearShadowLayer()
                    }
                },
                spaBuilder.indexOf(serviceSpan),
                spaBuilder.indexOf(serviceSpan) + serviceSpan.length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )
            return spaBuilder
        } catch (e: Exception) {
            return agreement
        }
    }

    companion object {
        fun launch(botId: Int) {
            appContext.startPage<DetailActivity>("robot_id" to botId)
        }
    }
}

class DetailHeaderAdapter() :
    BaseAdapter<CacheProfile, ItemDetailTitleBinding>() {
    override fun bindViewWithHolderDetails(
        holder: ViewHolder,
        item: CacheProfile?,
        binding: ItemDetailTitleBinding,
        position: Int
    ) {
         item ?: return
        binding.apply {
            tvContent.text = buildSpannedString {
                bold {
                    append(appContext.getString(R.string.intro))
                }
                append(item.personality)
            }
            "@${item.name}".also { tvAuth.text = it }
            tvAuth.isVisible = item.name.isEmpty() == false
            rvTag.isVisible = item.roleTag.isNotEmpty()
            if(item.roleTag.isNotEmpty()) {
                val adapter = HomeTagsAdapter()
                rvTag.layoutManager =  LinearLayoutManager(rvTag.context, RecyclerView.HORIZONTAL, false)
                rvTag.adapter =adapter
                adapter.updateList(item.roleTag.split(","))
            }
            rvTag.setOnTouchListener { _, _ ->
                true
            }
        }
    }

    override fun getItemViewType(position: Int): Int {
        return 100
    }
}

class DetailEmptyViewAdapter() :
    BaseAdapter<String, ViewDetailNoContentBinding>() {
    override fun bindViewWithHolderDetails(
        holder: ViewHolder,
        item: String?,
        binding: ViewDetailNoContentBinding,
        position: Int
    ) {
        binding.content.isVisible = true
        binding.icon.setImageResource(R.drawable.icon_no_content)
        binding.message.text = binding.root.context.getString(R.string.card_empty)
    }

    override fun getItemViewType(position: Int): Int {
        return 101
    }
}